package Gr

import (
	"errors"
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
	"sync/atomic"
)

type TableIndex struct {
}

type colAndWhereResult struct {
	selectColumn, asSelectColumn, whereCondition []string
	orderByColumn                                string
}

func (cs TableIndex) colAndWhere(s global.StartPart) (res colAndWhereResult, err error) {
	var (
		tableSql = TableSql{}
		event    = "[clusterStartPart]"
	)
	if res.selectColumn, res.asSelectColumn, err = tableSql.SelectColumn(s.SelectColumn); err != nil || len(res.selectColumn) == 0 {
		err = errors.New(fmt.Sprintf("%v get sql select Column fail. Execution process:{chema:%v,table:%v,select column:%v,err:%v}", event, s.TableInfo.Schema, s.TableInfo.BackendTableName, s.SelectColumn, err))
		return
	}
	if res.whereCondition, err = tableSql.WhereGenerate(s.WhereGenerate); err != nil {
		err = errors.New(fmt.Sprintf("%v get sql select where Condition fail. Execution process:{chema:%v,table:%v,select where Condition:%v,err:%v}", event, s.TableInfo.Schema, s.TableInfo.BackendTableName, s.WhereGenerate, err))
		return
	}
	return
}
func (cs TableIndex) selectCol(selectC []string) (r string) {
	var selectIndexColumn []string
	for _, v := range selectC {
		selectIndexColumn = append(selectIndexColumn, fmt.Sprintf("\"%v\"", v))
	}
	return strings.Join(selectIndexColumn, ",")
}
func (cs TableIndex) orderByNull(s global.StartPart) (r string) {
	return fmt.Sprintf(" order by `%v`", strings.Join(s.WhereGenerate.IndexColumn, "`,`"))
}
func (cs TableIndex) whereSplicing(whereCondition []string) (r string) {
	if len(whereCondition) > 0 {
		return fmt.Sprintf(" and %v", strings.Join(whereCondition, " and "))
	}
	return ""
}

/*
StartPart 库下查询表的索引列数据的始末位置，并进行去重排序
*/
func (cs TableIndex) StartPart(s global.StartPart) (result any, err error) {
	var (
		event = "[clusterStartPart]"
		f1    any
		rep   = global.StartPartReturnResult{}
		res   colAndWhereResult
	)
	active := ETL.InstanceActiveS{DBType: DBType, StopTime: s.Input.SqlExecStopTime, DB: s.DB[s.TableInfo.ShardName], SqlMode: s.Input.SqlMode}
	if res, err = cs.colAndWhere(s); err != nil {
		return
	}
	rep.BaseResult.Sql = fmt.Sprintf("select %v \n"+
		"from %v where 1= 1 \n"+
		"%v %v limit %d,1",
		strings.Join(res.selectColumn, ","),
		tableObject(s.TableInfo.Schema, s.TableInfo.BackendTableName, s.TableInfo.PartitionName),
		cs.whereSplicing(res.whereCondition), cs.orderByNull(s), atomic.LoadInt64(s.Limit.Pagination))
	if err = legitimateIf(event, rep.BaseResult.Sql, s, active); err != nil {
		return
	}
	if rep.BaseResult.TimeOut, f1, err = active.SqlQuery(rep.BaseResult.Sql, ETL.SMap); err != nil {
		err = errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", event, rep.BaseResult.Sql, "single", s.DB, err))
		return nil, err
	}
	rep.Result = f1.(map[string]any)
	return rep, nil
}
